package oneD.models;

import inf.v3d.view.Viewer;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import oneD.fem.Constraint;
import oneD.fem.structure.Structure;
import oneD.fem.visualize.TrussVisualizer;


public class TensegrityStructureViewer extends ModelViewer {
	protected ArrayList<Integer> elementGroup_;
	/*
	 * the elementGroup_ variable have the same length with number of elements
	 * and member i is the group id of element i
	 */
	private String filePath_;

	public TensegrityStructureViewer(String filePath) {
		this.filePath_ = filePath;
	}

	@Override
	public oneD.fem.structure.Tensegrity createStructure() {
		oneD.fem.structure.Tensegrity struct = new oneD.fem.structure.Tensegrity();
		TensegrityModelReader r = new TensegrityModelReader(this.filePath_);
		if (r.isReady()) {
			double[] d = null;
			do {
				try {
					d = r.readNextNode();
					if (d != null) {
						// System.out.println(d[0] + "," + d[1] + "," + d[2]);
						struct.addNode(d);
					}
				} catch (IOException e) {
					System.out.println(e.toString());
				}
			} while (d != null);

			r.reset();
			elementGroup_ = new ArrayList<Integer>();
			int[] i = null;
			do {
				try {
					i = r.readNextElement();
					if (i != null) {
						// System.out.println(i[0] + "," + i[1] + "," + i[2]);
						if (i[0] == 1)
							struct.addTrussElement(1, 2e7, 1, 0, i[1], i[2]);
						else
							struct.addCableElement(1, 2e3, 0.3, 0, i[1], i[2]);
						elementGroup_.add(new Integer(i[0]));
					}
				} catch (IOException e) {
					System.out.println(e.toString());
				}
			} while (i != null);
		}

		// set constraint

		// set force

		return struct;
	}

	@Override
	public void initializeVisualizer(Structure struct) {
		this.view_ = new Viewer();
		viz_ = new TrussVisualizer(struct, this.view_);
	}

	@Override
	public void visualize() {
		// set scaling factors
		d_max_ = viz_.automaticScale();
		// draw
		Set<Integer> s = new HashSet<Integer>(); // create a set of group index
													// to extract later on
		if (this.elementGroup_ != null) {
			// extract all the group id and put into set
			for (int i = 0; i < elementGroup_.size(); i++)
				s.add(elementGroup_.get(i));
			// draw each set of elements
			Iterator<Integer> it = s.iterator();
			int i = 0;
			while (it.hasNext()) {
				// Get element
				Integer e = (Integer) it.next();
				ArrayList<Integer> a = new ArrayList<Integer>();
				for (int j = 0; j < elementGroup_.size(); j++)
					if (e.equals(elementGroup_.get(j)))
						a.add(new Integer(j));
				this.viz_.drawElements(a, this.color_[i++]);
				i++;
			}
		}

		viz_.drawConstraints();
		viz_.drawForces();
		if (this.showNodeIdFlag_)
			viz_.showNodeId();
		if (this.showElementIdFlag_)
			viz_.showElementId();
		if (this.showElementGroupIdFlag_)
			viz_.showElementGroupId(this.elementGroup_);
	}

	public void setGroupConstraint(Structure struct, Constraint c,
			int elementGroupId) {
		/*
		 * set all the node belongs to all element in elementGroupId with
		 * constraint c
		 */
		for (int i = 0; i < struct.getNumberOfElements(); i++) {
			if (this.elementGroup_.get(i) == elementGroupId) {
				struct.getElement(i).getNode(0).setConstraint(c);
				struct.getElement(i).getNode(1).setConstraint(c);
			}
		}
	}

	protected void setConstraintOnNode(int nodeId, Structure struct,
			Constraint c) {
		struct.getNode(nodeId).setConstraint(c);
	}

	public ArrayList<Integer> getElementGroupId() {
		return this.elementGroup_;
	}
	
	@Override
	protected void performLinearModalAnalysis(Structure struct) {
		/*
		 * perform linear modal analysis
		 */
		System.out
				.println("This functionality is not supported for this model");
	}
}
